#include "network.h"
#include "iocp.h"
#include "epoll.h"
#include "select.h"
#include "crypter.h"
#ifdef _WIN32
#include <winsock2.h>
#else
#include <stddef.h>
#endif

MsgServer::~MsgServer()
{
    if(mImpl!=NULL)
    {
        delete mImpl;
        mImpl=NULL;
    }
}
MsgServer::MsgServer()
{
    mImpl=new MsgServerImpl();
}
void MsgServer::sethandler(IMsgHandler *hdl)
{
    mImpl->sethandler(hdl);
}
void MsgServer::start(const char* ipstr,unsigned short listenport)
{
    mImpl->start(ipstr,listenport);
}
void MsgServer::stop()
{
    mImpl->stop();
}
void MsgServer::runloop()
{
    mImpl->runloop();
}
void MsgServer::close(CrossSock s)
{
    mImpl->close(s);
}
void MsgServer::sendmessage(CrossSock s,NetMessage *msg,bool sendhead)
{
    mImpl->sendmessage(s,msg,sendhead);
}
void MsgServer::multi_sendmessage(MultiCrossSock* multiSock,NetMessage* msg,bool sendhead)
{
    mImpl->multi_sendmessage(multiSock,msg,sendhead);
}

MsgClient::~MsgClient()
{
    if(mImpl!=NULL)
    {
      delete mImpl;
      mImpl=NULL;
    }
}
MsgClient::MsgClient()
{
    mImpl=new MsgClientImpl();
}
void MsgClient::sethandler(IMsgHandler *hdl)
{
    mImpl->sethandler(hdl);
}
void MsgClient::start()
{
    mImpl->start();
}
void MsgClient::stop()
{
    mImpl->stop();
}
void MsgClient::runloop()
{
    mImpl->runloop();
}
void MsgClient::close(CrossSock s)
{
    mImpl->close(s);
}
void MsgClient::sendmessage(CrossSock s,NetMessage *msg,bool sendhead)
{
    mImpl->sendmessage(s,msg,sendhead);
}
void MsgClient::multi_sendmessage(MultiCrossSock* multiSock,NetMessage* msg,bool sendhead)
{
    mImpl->multi_sendmessage(multiSock,msg,sendhead);
}
bool MsgClient::connect(const char *dotip,unsigned short port,CrossSock *s)
{
    return mImpl->connect(dotip,port,s);
}

Connection::~Connection()
{
    if(mCrypt)
    {
        delete mCrypt;
        mCrypt=NULL;
    }
}

CryptMsgHandler::~CryptMsgHandler()
{
    delete mNet;
    mNet=NULL;
    delete mHdl;
    mHdl=NULL;
}

CryptMsgHandler::CryptMsgHandler(ICryptNet *net,IMsgHandler *hdl)
{
    mNet=net;
    mHdl=hdl;
}

void CryptMsgHandler::OnOpen(CrossSock s)
{
    mHdl->OnOpen(s);
}
void CryptMsgHandler::OnClosed(CrossSock s)
{
   mHdl->OnClosed(s);
}
void CryptMsgHandler::OnIllegal(CrossSock s,void *data,int datalen)
{
    mHdl->OnIllegal(s,data,datalen);
}
void CryptMsgHandler::OnPrevRecv(CrossSock s,void *data,int *datalen)
{
    mHdl->OnPrevRecv(s,data,datalen);
}

void CryptMsgHandler::OnReceived(CrossSock s,NetMessage *msg)
{
  Connection *conn=mNet->find_connection(s);
  if(!conn)
  {
    mHdl->OnIllegal(s,(void *)msg,msg->datalen+sizeof(msg->datalen));
    return;
  }
  Crypter *crypt=conn->GetCrypter();
  if(!crypt)
  {
    mHdl->OnReceived(s,msg);
    return;
  }
  if(!crypt->NeedDeCode(msg))
  {
    mHdl->OnReceived(s,msg);
    return;
  }
  NetMessage *outmsg=createmessage();
  int outlen=NET_MESSAGE_SIZE;
  if(!crypt->DeCode((byte *)msg->data,msg->datalen,(byte *)outmsg->data,&outlen))
  {
    destroymessage(outmsg);
    mHdl->OnIllegal(s,(void *)msg,msg->datalen+sizeof(msg->datalen));
    return;
  }
  outmsg->datalen=outlen;
  if(outmsg->datalen>NET_MESSAGE_SIZE)
  {
      assert(0);
      destroymessage(outmsg);
      mHdl->OnIllegal(s,(void *)msg,msg->datalen+sizeof(msg->datalen));
      return;
  }
  mHdl->OnReceived(s,outmsg);
  destroymessage(outmsg);
}

bool CryptMsgHandler::OnSend(CrossSock s,NetMessage *&msg,bool sendhead)
{
  Connection *conn=mNet->find_connection(s);
  if(!conn)
  {
    return false;
  }
  Crypter *crypt=conn->GetCrypter();
  if(!crypt)
  {
    return mHdl->OnSend(s,msg,sendhead);
  }
  if(!crypt->NeedEnCode(msg))
  {
    return mHdl->OnSend(s,msg,sendhead);
  }
  NetMessage *outmsg=createmessage();
  int outlen=NET_MESSAGE_SIZE;
  if(!crypt->EnCode((byte *)msg->data,msg->datalen,(byte *)outmsg->data,&outlen))
  {
    destroymessage(outmsg);
    return false;
  }
  outmsg->datalen=outlen;
  if(outmsg->datalen>NET_MESSAGE_SIZE)
  {
      assert(0);
      destroymessage(outmsg);
      return false;
  }
  destroymessage(msg);
  msg=outmsg;
  return mHdl->OnSend(s,msg,sendhead);
}
